﻿using System.Collections.Generic;
using System.IO;
using System.Text;


namespace CIAWorldMap
{
    public class LaosBorder
    {
        public readonly Dictionary<int, string> _laosBorderSegmentIds = new Dictionary<int, string>();
        public readonly Dictionary<string, MapSegment> _laosSegments = new Dictionary<string, MapSegment>();
        public List<Coord> _geoPolygon = new List<Coord>();

        public LaosBorder()
        {
            var laosBorderSegmentIds1 = new[]{
             
                1311 ,
                139 ,
                111 ,
                112 ,
                113 , //?
                114,
                115 ,
                101 ,
                102 , //?
                103 ,
                100 ,
                99 ,
                98 ,
                97 , //?
                122 ,
                121 ,
                120 ,
                119, 
                118 , 
                1312 ,
           
            };
            foreach (var i in laosBorderSegmentIds1)
            {
                _laosBorderSegmentIds.Add(i, "");
            }
        }

        public void LoadBorder(string fileName)
        {
            if (!File.Exists(fileName))
            {
                return;
            }

            _geoPolygon.Clear();

            FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);

            var unicode = new UnicodeEncoding();

            using (var br = new BinaryReader(fs, unicode))
            {
                int polygonCoordCount = br.ReadInt32();

                for (int x = 0; x < polygonCoordCount; x++)
                {
                    double lat = br.ReadDouble();
                    double lon = br.ReadDouble();
                    Coord c = new Coord(lat, lon);
                    _geoPolygon.Add(c);
                }
                br.Close();
            }
        }

        public void SaveBorder(string fileName)
        {
            if (_geoPolygon.Count == 0)
            {
                return;
            }

            if (File.Exists(fileName))
            {
                File.Delete(fileName);
            }

            FileStream fs = File.Create(fileName);

            var unicode = new UnicodeEncoding();

            using (var bw = new BinaryWriter(fs, unicode))
            {
                bw.Write(_geoPolygon.Count);

                foreach (var coord in _geoPolygon)
                {
                    bw.Write(coord._lat);
                    bw.Write(coord._lon);
                }
                bw.Flush();
                bw.Close();
            }
        }

        public bool AddBorder(MapSegment curentSeg, string line)
        {
            string[] sz = line.Split(' ');
            int segmentId = int.Parse(sz[1]);

            if (!_laosBorderSegmentIds.ContainsKey(segmentId))
                return false;

            if (!_laosSegments.ContainsKey(line))
            {
                _laosSegments.Add(line, curentSeg);
            }
            return true;
        }

        private void BuildGeoPolygon()
        {
            _geoPolygon.Clear();
            foreach (string skey in _laosBorderSegmentIds.Values)
            {
                MapSegment s = _laosSegments[skey];

                foreach (Coord c in s._coords)
                {
                    _geoPolygon.Add(c);
                }
            }
        }

        public void LaosBorderSetSgments()
        {
            if (_laosSegments.Count == 0)
                return;

            foreach (string skey1 in _laosSegments.Keys)
            {
                string[] sz = skey1.Split(' ');
                int segmentId = int.Parse(sz[1]);
                MapSegment s = _laosSegments[skey1]; // avoid a zero length segment 97 from overwriting a valid 97
                if (s._coords.Count != 0)
                {
                    _laosBorderSegmentIds[segmentId] = skey1;

                    List<Coord> temp = new List<Coord>();
                    temp.AddRange(s._coords);

                    switch (segmentId)
                    {
                        case 97:
                        case 98:
                        case 99:
                        case 100:
                        case 102:
                        case 118:
                        case 119:
                        case 120:
                        case 121:
                        case 122:
                        case 1311:
                        case 1312:
                            temp.Reverse();
                            s._coords = temp;
                            break;
                    }
                }
            }
            BuildGeoPolygon();
        }

        public bool PointInPolygon(Coord p)
        {
            Coord p1, p2;

            bool inside = false;

            if (_geoPolygon.Count < 3)
            {
                return inside;
            }

            Coord oldPoint = new Coord(_geoPolygon[_geoPolygon.Count - 1]._lat, _geoPolygon[_geoPolygon.Count - 1]._lon);

            for (int i = 0; i < _geoPolygon.Count; i++)
            {
                Coord newPoint = new Coord(_geoPolygon[i]._lat, _geoPolygon[i]._lon);

                if (newPoint._lon > oldPoint._lon)
                {
                    p1 = oldPoint;
                    p2 = newPoint;
                }
                else
                {
                    p1 = newPoint;
                    p2 = oldPoint;
                }

                if ((newPoint._lon < p._lon) == (p._lon <= oldPoint._lon) &&
                    (p._lat - p1._lat) * (p2._lon - p1._lon) < (p2._lat - p1._lat) * (p._lon - p1._lon))
                {
                    inside = !inside;
                }

                oldPoint = newPoint;
            }
            return inside;
        }

    }
}
